#ifndef QJSONSERIALIZE_H
#define QJSONSERIALIZE_H

#include <QString>
#include <QMap>
#include <QList>
#include <QVector>
#include <QSet>
#include <QDate>
#include <QDateTime>
#include <QUrl>
#include <QUuid>
#include "nlohmann/json.hpp"

using json = nlohmann::json;

// 基础 Qt 类型序列化支持
namespace nlohmann {
// 1. QString
template<>
struct adl_serializer<QString> {
    static void to_json(json& j, const QString& qstr) {
        j = qstr.toStdString();
    }

    static void from_json(const json& j, QString& qstr) {
        if (j.is_null()) {
            qstr.clear();
        } else {
            qstr = QString::fromStdString(j.get<std::string>());
        }
    }
};

// 2. QList<T>
template<typename T>
struct adl_serializer<QList<T>> {
    static void to_json(json& j, const QList<T>& list) {
        j = json::array();
        for (const auto& item : list) {
            j.push_back(item);
        }
    }

    static void from_json(const json& j, QList<T>& list) {
        list.clear();
        if (!j.is_array()) return;

        for (const auto& item : j) {
            list.append(item.get<T>());
        }
    }
};

// 3. QVector<T>
template<typename T>
struct adl_serializer<QVector<T>> {
    static void to_json(json& j, const QVector<T>& vec) {
        j = json::array();
        for (const auto& item : vec) {
            j.push_back(item);
        }
    }

    static void from_json(const json& j, QVector<T>& vec) {
        vec.clear();
        if (!j.is_array()) return;

        for (const auto& item : j) {
            vec.append(item.get<T>());
        }
    }
};

// 4. QSet<T> - 注意：QSet 没有顺序，转换为数组
template<typename T>
struct adl_serializer<QSet<T>> {
    static void to_json(json& j, const QSet<T>& set) {
        j = json::array();
        for (const auto& item : set) {
            j.push_back(item);
        }
    }

    static void from_json(const json& j, QSet<T>& set) {
        set.clear();
        if (!j.is_array()) return;

        for (const auto& item : j) {
            set.insert(item.get<T>());
        }
    }
};

// 5. QDate
template<>
struct adl_serializer<QDate> {
    static void to_json(json& j, const QDate& date) {
        if (date.isValid()) {
            j = date.toString(Qt::ISODate).toStdString();
        } else {
            j = nullptr;
        }
    }

    static void from_json(const json& j, QDate& date) {
        if (j.is_null()) {
            date = QDate();
        } else {
            date = QDate::fromString(QString::fromStdString(j.get<std::string>()), Qt::ISODate);
        }
    }
};

// 6. QDateTime
template<>
struct adl_serializer<QDateTime> {
    static void to_json(json& j, const QDateTime& datetime) {
        if (datetime.isValid()) {
            j = datetime.toString(Qt::ISODate).toStdString();
        } else {
            j = nullptr;
        }
    }

    static void from_json(const json& j, QDateTime& datetime) {
        if (j.is_null()) {
            datetime = QDateTime();
        } else {
            datetime = QDateTime::fromString(QString::fromStdString(j.get<std::string>()), Qt::ISODate);
        }
    }
};

// 7. QUrl
template<>
struct adl_serializer<QUrl> {
    static void to_json(json& j, const QUrl& url) {
        j = url.toString().toStdString();
    }

    static void from_json(const json& j, QUrl& url) {
        url = QUrl(QString::fromStdString(j.get<std::string>()));
    }
};

// 8. QUuid
template<>
struct adl_serializer<QUuid> {
    static void to_json(json& j, const QUuid& uuid) {
        j = uuid.toString().toStdString();
    }

    static void from_json(const json& j, QUuid& uuid) {
        uuid = QUuid(QString::fromStdString(j.get<std::string>()));
    }
};

// 9. QMap<QString, T> - 通用版本
template<typename T>
struct adl_serializer<QMap<QString, T>> {
    static void to_json(json& j, const QMap<QString, T>& map) {
        j = json::object();
        for (auto it = map.constBegin(); it != map.constEnd(); ++it) {
            j[it.key().toStdString()] = it.value();
        }
    }

    static void from_json(const json& j, QMap<QString, T>& map) {
        map.clear();
        if (!j.is_object()) return;

        for (auto it = j.begin(); it != j.end(); ++it) {
            QString key = QString::fromStdString(it.key());
            T value = it.value().get<T>();
            map[key] = value;
        }
    }
};

// 10. QPair<T1, T2>
template<typename T1, typename T2>
struct adl_serializer<QPair<T1, T2>> {
    static void to_json(json& j, const QPair<T1, T2>& pair) {
        j = json::array({pair.first, pair.second});
    }

    static void from_json(const json& j, QPair<T1, T2>& pair) {
        if (!j.is_array() || j.size() != 2) return;

        pair.first = j[0].get<T1>();
        pair.second = j[1].get<T2>();
    }
};
}

#endif // QJSONSERIALIZE_H
